package com.zhangxu.microservice.gateway.filter;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.util.Objects;
import java.util.Set;

@Component
@RequiredArgsConstructor
@Slf4j
public class PermissionAuthFilter implements GlobalFilter, Ordered {

    private final RedissonClient redissonClient;
    private static final String PREFIX = "auth:token:";


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String authorization = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
        String method = request.getMethod().name();
        String path = request.getPath().toString();
        // ====== 白名单放行配置 ======
        if (isWhiteListed(path)) {
            log.info("白名单放行，method:{}, path:{}", method, path);
            return chain.filter(exchange);
        }
        if (!StringUtils.hasText(authorization) || !authorization.startsWith("Bearer ")) {
            return unauthorized(exchange);
        }
        String token = authorization.replace("Bearer ", "");
        RBucket<Long> bucket = redissonClient.getBucket(PREFIX + token);
        //续期半小时
        Long userId = bucket.getAndExpire(Duration.ofMinutes(30));

        log.info("用户ID:{},method:{},path:{}", userId, method, path);
        if (Objects.nonNull(userId)) {
            ServerHttpRequest mutatedRequest = request.mutate()
                    .header("employeeId", userId.toString())
                    .build();
            return chain.filter(exchange.mutate().request(mutatedRequest).build());
        }
        // 从 Redis 获取用户权限集合
//        String key = "perm:user:" + userId;
//        Set<String> perms = redisTemplate.opsForSet().members(key);
//
//        if (perms != null && !perms.isEmpty()) {
//            // 从 Redis 获取路径对应权限码
//            String permCode = redisTemplate.opsForValue().get("perm:path:" + method + ":" + path);
//
//            if (permCode != null && perms.contains(permCode)) {
//                return chain.filter(exchange);
//            }
//        }
        return unauthorized(exchange);
    }

    /**
     * 白名单路径匹配
     */
    private boolean isWhiteListed(String path) {
        // Swagger 聚合文档白名单
        if (path.startsWith("/v3/api-docs") ||
                path.startsWith("/swagger-ui.html") ||
                path.startsWith("/swagger-ui/") ||
                path.startsWith("/webjars/") ||
                path.matches("^/api/.*/v3/api-docs.*")) {
            return true;
        }

        // 放行登录/无权限接口
        if (path.startsWith("/api/system/noRight")) {
            return true;
        }

        return false;
    }

    private Mono<Void> unauthorized(ServerWebExchange exchange) {
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        return exchange.getResponse().setComplete();
    }

    private Mono<Void> forbidden(ServerWebExchange exchange) {
        exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
        return exchange.getResponse().setComplete();
    }

    @Override
    public int getOrder() {
        return -150;
    }
}
